package com.fin.quant.job.schedule;

import com.fin.quant.app.asset.service.AssetService;
import com.fin.quant.app.service.DividendService;
import com.fin.quant.common.TradeUtil;
import com.fin.quant.domain.entity.AssetEntity;
import com.fin.quant.instra.mysql.model.Asset;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Component
public class DividendRefreshJob {

    @Autowired
    private DividendService dividendService;

    @Autowired
    private AssetService assetService;

    // 创建Guava Cache缓存assetIdList，过期时间设置为10分钟
    private final Cache<String, List<Long>> assetIdListCache = CacheBuilder.newBuilder()
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .build();

    // 创建Guava限流器，每秒允许最多10个任务执行
    private final RateLimiter rateLimiter = RateLimiter.create(1);

    private ThreadPoolExecutor tpe = new ThreadPoolExecutor(100, 256, 5, TimeUnit.MINUTES, new LinkedBlockingDeque<>(10000), new ThreadPoolExecutor.CallerRunsPolicy());

    @Scheduled(fixedDelay = 5 * 1000)
    public void refreshDividend() {
        List<Long> assetIdList = getAssetIdList();
        assetIdList.forEach(assetId -> {
            tpe.execute(() -> {
                try {
                    // 获取限流许可
                    rateLimiter.acquire();
                    log.info("refreshDividend assetId={}", assetId);
                    dividendService.updateAssetDividendInfo(assetId);
                } catch (Exception ex) {
                    log.error("refreshDividend error.", ex);
                }
            });
        });
    }

    private List<Long> getAssetIdList() {
        // 从缓存中获取
        List<Long> cachedAssetIdList = assetIdListCache.getIfPresent("assetIdList");
        if (cachedAssetIdList != null) {
            return cachedAssetIdList;
        }

        List<AssetEntity> allAssets = assetService.getAllAssets();
        List<Long> assetIdList = allAssets.stream().map(AssetEntity::getId).collect(Collectors.toList());
        // 放入缓存
        assetIdListCache.put("assetIdList", assetIdList);
        return assetIdList;
    }


    //@Scheduled(fixedDelay = 5 * 1000)
    public void refreshCurrentDividendYield() {
        if (TradeUtil.isTradingTime()) {
            List<Long> assetIdList = getAssetIdList();
            assetIdList.forEach(assetId -> {
                tpe.execute(() -> {
                    try {
                        log.info("refreshCurrentDividendYield assetId={}", assetId);
                        dividendService.getCurrentDividendYield(assetId);
                    } catch (Exception e) {
                        log.info("refreshCurrentDividendYield assetId={}", assetId, e);
                    }
                });
            });
        }
    }

    //@Scheduled(fixedDelay = 5 * 1000)
    public void refreshCloseDividendYield() {
        if (TradeUtil.isTradingTime()) {

        } else {
            List<Long> assetIdList = getAssetIdList();
            assetIdList.forEach(assetId -> {
                tpe.execute(() -> {
                    try {
                        log.info("refreshCloseDividendYield assetId={}", assetId);
                        dividendService.getCloseDividendYield(assetId);
                    } catch (Exception e) {
                        log.info("refreshCloseDividendYield assetId={}", assetId, e);
                    }
                });
            });
        }
    }

}

